package Leetcode.网格图;

import java.util.ArrayDeque;
import java.util.Queue;

/**
 * @Author: kirito
 * @Date: 2024/5/8 16:00
 * @Description:
 * 最短的桥
 * 中等
 * 相关标签
 * 相关企业
 * 给你一个大小为 n x n 的二元矩阵 grid ，其中 1 表示陆地，0 表示水域。
 *
 * 岛 是由四面相连的 1 形成的一个最大组，即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛 。
 *
 * 你可以将任意数量的 0 变为 1 ，以使两座岛连接起来，变成 一座岛 。
 *
 * 返回必须翻转的 0 的最小数目。
 *
 *
 *
 * 示例 1：
 *
 * 输入：grid = [[0,1],[1,0]]
 * 输出：1
 * 示例 2：
 *
 * 输入：grid = [[0,1,0],[0,0,0],[0,0,1]]
 * 输出：2
 * 示例 3：
 *
 * 输入：grid = [[1,1,1,1,1],[1,0,0,0,1],[1,0,1,0,1],[1,0,0,0,1],[1,1,1,1,1]]
 * 输出：1
 *
 *
 * 提示：
 *
 * n == grid.length == grid[i].length
 * 2 <= n <= 100
 * grid[i][j] 为 0 或 1
 * grid 中恰有两个岛
 */

public class shortestBridge {
    /**
     * 可以先找到其中一片岛屿，运用DFS把它标识为2，与另一片岛屿进行区分，也防止重复遍历
     * 在1的标识过程中，收集第一片岛屿附近的海洋（最近一层的海洋0），加入队列queue
     * BFS搜索队列，逐层往外“填海造陆”，直到遇到第二片岛屿
     * @param grid
     * @return
     */
    public int shortestBridge(int[][] grid) {
        int n = grid.length;
        int[][] dirs = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] != 1) {
                    continue;
                }
                //此时找到第一个岛屿
                Queue<int[]> queue = new ArrayDeque<int[]>();
                dfs(i, j, grid, queue);
                int step = 0;
                while (!queue.isEmpty()) {
                    int sz = queue.size();
                    //遍历每一层的que
                    for (int k = 0; k < sz; k++) {
                        int[] cell = queue.poll();
                        int x = cell[0], y = cell[1];
                        //四个方向
                        for (int d = 0; d < 4; d++) {
                            int nx = x + dirs[d][0];
                            int ny = y + dirs[d][1];
                            if (nx >= 0 && ny >= 0 && nx < n && ny < n) {
                                //填海
                                if (grid[nx][ny] == 0) {
                                    queue.offer(new int[]{nx, ny});
                                    grid[nx][ny] = -1;
                                //找到另一个小岛
                                } else if (grid[nx][ny] == 1) {
                                    return step;
                                }
                            }
                        }
                    }
                    //遍历完一层que后step+1
                    step++;
                }
            }
        }
        return 0;
    }

    public void dfs(int x, int y, int[][] grid, Queue<int[]> queue) {
        if (x < 0 || y < 0 || x >= grid.length || y >= grid[0].length || grid[x][y] != 1) {
            return;
        }
        queue.offer(new int[]{x, y});
        grid[x][y] = -1;
        dfs(x - 1, y, grid, queue);
        dfs(x + 1, y, grid, queue);
        dfs(x, y - 1, grid, queue);
        dfs(x, y + 1, grid, queue);
    }
}
